import graph_tool as gt
import graph_tool.draw as gt_draw
import graph_tool.spectral as gts
import numpy as np
from itertools import izip

def test():
    # file = "/Users/rockyrock/Desktop/Netwoks/data/facebook/107.edges"
    file = "./edges.txt"
    graph = read_graph(file)
    gt_draw.graph_draw(graph.g, vertex_text=graph.g.vp["names"], output="ed46.png")
    
class Graph:
    """
    Parameters:
        g: graph-tool graph object.
        data: a features 2D array (matrix) for all the possible edges in the graph. 
              Each row in the matrix represents a feature vector for the 
              edge (v1_v2). The edge (v1_v2) is the edge id, where v1 is the vertex label. 
              This matrix has a feature vector for every possible edge in the graph. 
              So there is always a row for (v1_v2).
        target: an array that holds whether two vertices (an edge id v1_v2) has a 
                real link or not in the graph. The indices correspond to the rows
                in the data matrix.
        edges_ids: an array that holds the edges ids (of the form v1_v2) in the graph. 
                   The index of each edge id is the same as the row index of data array. 
        label_to_index: is a dictionary that maps from a vertex label to vertex index.
        v_to_label: is a dictionary that maps from a graph_tool vertex object to vertex label.
    """
    def __init__(self):
        self.g = None
        self.label_to_index = None
        self.v_to_label = None
        self.data = None
        self.target = None
        self.edges_ids= None
    
    def get_vertix(self, label):
        index = self.label_to_index[label]
        v = self.g.vertex(index)
        return v
    
    def get_v_label(self, vertix):
        label = self.v_to_label[vertix]
        return label
    
    def get_v_index(self, label):
        index = self.label_to_index[label]
        return index
    
    def from_edgeID_to_dataIndex(self, edgeID):
        dataIndex = None
        
        v1_label = edgeID.split('_')[0]
        v2_label = edgeID.split('_')[1]
        id1 = v1_label + '_' + v2_label
        id2 = v2_label + '_' + v1_label
        
        if id1 and id2 in self.edges_ids:
            raise Exception("There are duplicate edges ids and so duplicate feature vectors!!!")
        elif id1 in self.edges_ids:
            dataIndex = self.edges_ids.index(id1)
        elif id2 in self.edges_ids:
            dataIndex = self.edges_ids.index(id2)
            
        return dataIndex
    
    def get_feature_vector(self, edgeID):
        dataIndex = self.from_edgeID_to_dataIndex(edgeID)
        vector = self.data[dataIndex]
        return vector
    
    def v_labels(self):
        return self.label_to_index.keys()
    
    def v_indices(self):
        return self.label_to_index.values()
    
    
    def v_items(self):
        """
        Returns a list of tuples of the form (vertex label, vertex index)
        """
        return self.label_to_index.items()
    
def build_edges_ids(v_labels_list):
    edges_ids = list()
 
    for i, label_1 in enumerate(v_labels_list):
        for label_2 in v_labels_list[i+1:]:
            edge_id = label_1 + '_' + label_2
            edges_ids.append(edge_id)
                
    return edges_ids

def from_edgeID_to_vertix_labels(edge_id):
    v1_label = edge_id.split('_')[0]
    v2_label = edge_id.split('_')[1]
    return v1_label, v2_label

def read_graph(file_path):
    """
        Read a text file that has the following format: source target
        It returns 
        1 - a graph constrcuted by connecting the source and target with edges.
        2- the vertices dictionary that maps the vertices names to their indices.
    """
    edges_file_path = file_path
    graph = gt.Graph(directed=False)
    vtext = graph.new_vertex_property("string")
    graph.vertex_properties["names"] = vtext
    vertices_names_to_indices = {}
    with open(edges_file_path, 'r') as edges_file:
        for line in edges_file:
            line = line.rstrip()
            row = line.split(' ') 
            if len(row) != 2:
                raise Exception("There are more than two nodes in a row in the edges file!")
            source = row[0]
            target = row[1]
            sindex = None
            tindex = None
            
            if source in vertices_names_to_indices:
                sindex = vertices_names_to_indices[source]
            else:
                v1 = graph.add_vertex()
                sindex = int(v1)
                vertices_names_to_indices[source] = sindex
                vtext[v1] = source
                
            if target in vertices_names_to_indices:
                tindex = vertices_names_to_indices[target]
            else:
                v2 = graph.add_vertex()
                tindex = int(v2)
                vertices_names_to_indices[target] = tindex
                vtext[v2] = target
            
            graph.add_edge(sindex, tindex)
    
#     gt_draw.graph_draw(graph, vertex_text=vtext, output="kkked.png")
    
    #Creating the graph object
    g = Graph()
    g.g = graph
    g.label_to_index = vertices_names_to_indices
    g.v_to_label = vtext
    edges_ids = build_edges_ids(g.v_labels())
    g.edges_ids = edges_ids
     
    A = gts.adjacency(graph)
    A = A.toarray()
    target = list()
    for edge_id in edges_ids:
        v1_label, v2_label = from_edgeID_to_vertix_labels(edge_id)
        v1_index = g.get_v_index(v1_label)
        v2_index = g.get_v_index(v2_label)
             
        if A[v1_index, v2_index] == 1:
            target.append(1)
        else:
            target.append(0)
    g.target = target
     
    return g
    
def make_edge_id(v1, v2):
    index1 = int(v1)
    index2 = int(v2)
    edge_id = "%d_%d" % (index1, index2)
    return edge_id
    
# gt_tests()





















